//
// Created by YE on 2024/1/16.
//

#ifndef YCH_INTERPRETER_CODER_H
#define YCH_INTERPRETER_CODER_H

#include "parser.h"
#include "symbols.h"
#include "../vm/instruction.h"

#define SEM_OK 0
#define SEM_ERROR 2
#define SEM_MEM_OVERFLOW_ERROR 3
#define SEM_TYPE_ERROR 4
#define SEM_REDECLARATION_VAR_ERROR 5
#define SEM_UNDEFINED_VAR_ERROR 6
#define SEM_STACK_ERROR 7
#define SEM_BREAK_NOT_IN_LOOP_STRUCT_ERROR 8
#define SEM_UNDEFINED_FUNCTION_ERROR 9
#define SEM_FUNC_PARAM_ERROR 10
#define SEM_REDEF_FUNC_ERROR  11

void load_Clib(CState *cs);

static void code_op(CState *cs, unsigned int opcode);

static void code_ABC(CState *cs, unsigned int opcode, unsigned int a, unsigned int b, unsigned int c);

static void code_ABx(CState *cs, unsigned int opcode, unsigned int a, unsigned int bx);

Sem_State operate(Parser *p, T ac);

static bool find_var(Parser *parser, unsigned int *p);

static bool find_func(String *vn, FuncInfo *f);

static bool find_int(Int i, unsigned int *p);

static bool find_float(Float i, unsigned int *p);
static bool find_string(String &vn, unsigned int *p);

static Sem_State alloc_var(CState *cs, unsigned int *p);

static Sem_State alloc_int(CState *cs, unsigned int *p);

static Sem_State alloc_float(CState *cs, unsigned int *p);
static Sem_State alloc_string(CState *cs, unsigned int *p);

static Sem_State find_and_alloc_int(CState *cs, Int i, unsigned int *p);

static Sem_State find_and_alloc_float(CState *cs, Float i, unsigned int *p);

static Sem_State ac_sem_pop(CState *cs, Sen_Stack *sem);

static Sem_State ac_pop(CState *cs, Sen_Stack *sem);

static Sem_State ac_assign_end(CState *cs, Sen_Stack *sem);

static Sem_State ac_push_assign(CState *cs, Sen_Stack *sem);

static Sem_State ac_set_ekind(CState *cs, Token *token);

static Sem_State ac_malloc_var(Parser* parser);

static Sem_State ac_push_const(CState *cs, Sen_Stack *sem, Token *token);

static Sem_State ac_neg(CState *cs, Sen_Stack *sem);

static Sem_State ac_not(CState *cs, Sen_Stack *sem);

static Sem_State ac_inner(CState *cs, Sen_Stack *sem);
static Sem_State ac_double_compute(CState *cs, Sen_Stack *sem, OP op);

static Sem_State ac_sem_push_var(Parser* parser);

static Sem_State ac_push_func(CState *cs, Sen_Stack *sem,Token *token);

static Sem_State ac_func_count(CState *cs, Sen_Stack *sem);

static Sem_State ac_func_end(CState *cs, Sen_Stack *sem);

static void set_Int(unsigned int mp, Int i);

static void set_Float(unsigned int mp, Float f);

static void set_Bool(unsigned int mp, bool b);

static void set_Mat(unsigned int mp);
static void set_String(unsigned int mp);
static Sem_State gen_assign_first_code(CState *cs, Sen_Stack *sem);

static Sem_State ac_push_while(CState *cs, Sen_Stack *sem);

static Sem_State ac_judge(CState *cs, Sen_Stack *sem, Sen_Stack *if_sem, bool b);

static Sem_State ac_while_end(CState *cs, Sen_Stack *sem);

static Sem_State ac_while_break(CState *cs, Sen_Stack *sem);

static Sem_State ac_if_end(CState *cs, Sen_Stack *if_sem);

static Sem_State ac_push_else(CState *cs, Sen_Stack *if_sem);

static Sem_State ac_else_end(CState *cs, Sen_Stack *if_sem);

static Sem_State ac_def_func_start(CState *cs, Sen_Stack *sem, Token *token);

static Sem_State ac_def_count_params(Parser* parser);

static Sem_State ac_return(CState *cs, Sen_Stack *sem);

static Sem_State ac_def_func_end(CState *cs, Sen_Stack *sem);

static Sem_State ac_mat_count_row(Parser* parser);
static Sem_State ac_mat_count_col(Parser* parser);
static Sem_State ac_mat_start(Parser* parser);
static Sem_State ac_mat_end(Parser* parser);
static Sem_State ac_index(Parser* parser);
#endif //YCH_INTERPRETER_CODER_H
